﻿﻿﻿﻿using jiuyuan.数据.共享类;
using jiuyuan.数据.基础数据类;
using jiuyuan.数据.玩家类;
using jiuyuan.服务;

namespace jiuyuan.管理器;

// 装备槽位枚举
public enum 装备槽位
{
    武器,
    头盔,
    胸甲,
    护腿,
    靴子,
    项链,
    戒指1,
    戒指2,
    饰品
}

// 装备物品类
public class 装备物品 : 游戏元素
{
    public 装备槽位 槽位 { get; set; }
    public int 耐久度 { get; set; }
    public int 最大耐久度 { get; set; }
    public List<装备特效> 特效列表 { get; set; } = [];
}

// 装备特效基类
public abstract class 装备特效
{
    public int Id { get; set; }
    public string 特效名称 { get; set; } = string.Empty;
    public string 特效描述 { get; set; } = string.Empty;
    public abstract void 应用特效(玩家 玩家, 战斗上下文? 战斗上下文 = null);
    public abstract void 移除特效(玩家 玩家);
}

// 具体装备特效实现
public class 属性加成特效 : 装备特效
{
    public 属性配置 加成属性 { get; set; } = new 属性配置();

    public override void 应用特效(玩家 玩家, 战斗上下文? 战斗上下文 = null)
    {
        玩家.当前属性 = 属性配置.合并属性(玩家.当前属性, 加成属性);
    }

    public override void 移除特效(玩家 玩家)
    {
        玩家.当前属性 = 属性配置.合并属性(玩家.当前属性, 负属性(加成属性));
    }

    static 属性配置 负属性(属性配置 属性)
        => new()
        {
            生命值 = -属性.生命值,
            魔法值 = -属性.魔法值,
            物理攻击 = -属性.物理攻击,
            物理防御 = -属性.物理防御,
            火属性攻击 = -属性.火属性攻击,
            水属性攻击 = -属性.水属性攻击,
            风属性攻击 = -属性.风属性攻击,
            土属性攻击 = -属性.土属性攻击,
            火属性抗性 = -属性.火属性抗性,
            水属性抗性 = -属性.水属性抗性,
            风属性抗性 = -属性.风属性抗性,
            土属性抗性 = -属性.土属性抗性,
            速度 = -属性.速度,
            幸运值 = -属性.幸运值
        };
    }

public class 技能增强特效 : 装备特效
{
    public string 技能名称 { get; set; } = string.Empty;
    public float 伤害加成 { get; set; } = 1.0f;
    public int 额外效果回合 { get; set; } = 0;

    public override void 应用特效(玩家 玩家, 战斗上下文? 战斗上下文 = null)
    {
        // 这个特效在技能执行时生效
        // 可以通过事件总线监听技能使用事件
    }

    public override void 移除特效(玩家 玩家)
    {
        // 移除特效
    }
}

// 装备管理器
public class 装备管理器
{
    private readonly 事件总线 _事件总线;
    private readonly ILogger<装备管理器> _日志器;
    private readonly Dictionary<Guid, 装备物品> _装备字典 = [];
    private readonly Dictionary<装备槽位, 装备物品?> _默认装备 = [];

    public 装备管理器(事件总线 事件总线, ILogger<装备管理器> 日志器)
    {
        _事件总线 = 事件总线;
        _日志器 = 日志器;
        初始化默认装备();
        注册事件处理();
    }

    /// <summary>
    /// 初始化默认装备
    /// </summary>
    private void 初始化默认装备()
    {
        foreach (装备槽位 槽位 in Enum.GetValues(typeof(装备槽位)))
        {
            _默认装备[槽位] = null;
        }
    }

    /// <summary>
    /// 注册装备
    /// </summary>
    public void 注册装备(装备物品 装备)
    {
        _装备字典[装备.Id] = 装备;
        _日志器.LogInformation("注册装备: {装备名称}, 槽位: {装备槽位}", 装备.名称, 装备.槽位);
    }

    /// <summary>
    /// 根据ID获取装备
    /// </summary>
    public 装备物品? 获取装备(Guid 装备ID)
    {
        return _装备字典.TryGetValue(装备ID, out var 装备) ? 装备 : null;
    }

    /// <summary>
    /// 穿戴装备
    /// </summary>
    public async Task<bool> 穿戴装备(玩家 玩家, 装备物品 装备)
    {
        if (装备.类型 != 物品类型.装备)
        {
            _日志器.LogWarning("物品 {物品名称} 不是装备，无法穿戴", 装备.名称);
            return false;
        }

        // 检查等级要求
        if (玩家.等级 < 装备.等级要求)
        {
            _日志器.LogWarning("玩家 {玩家名称} 等级不足，无法穿戴 {装备名称}", 玩家.名称, 装备.名称);
            return false;
        }

        // 检查槽位是否已被占用
        var 当前装备 = 获取槽位装备(玩家, 装备.槽位);
        if (当前装备 != null)
        {
            // 先脱下当前装备
            await 脱下装备(玩家, 装备.槽位);
        }

        // 添加到装备列表
        玩家.装备列表.Add(装备);

        // 应用装备特效
        foreach (var 特效 in 装备.特效列表)
        {
            特效.应用特效(玩家);
        }

        // 重新计算玩家属性
        玩家.重新计算属性();

        _日志器.LogInformation("玩家 {玩家名称} 穿戴装备 {装备名称} 到 {槽位} 槽位",
            玩家.名称, 装备.名称, 装备.槽位);

        // 发布装备穿戴事件
        await _事件总线.发布事件(new 装备穿戴事件
        {
            玩家 = 玩家,
            装备 = 装备,
            槽位 = 装备.槽位
        });

        return true;
    }

    /// <summary>
    /// 脱下装备
    /// </summary>
    public async Task<bool> 脱下装备(玩家 玩家, 装备槽位 槽位)
    {
        var 装备 = 获取槽位装备(玩家, 槽位);
        if (装备 == null)
        {
            _日志器.LogWarning("玩家 {玩家名称} 在 {槽位} 槽位没有穿戴装备", 玩家.名称, 槽位);
            return false;
        }

        // 从装备列表移除
        bool 移除成功 = 玩家.装备列表.Remove(装备);
        if (移除成功)
        {
            // 移除装备特效
            foreach (var 特效 in 装备.特效列表)
            {
                特效.移除特效(玩家);
            }

            // 重新计算玩家属性
            玩家.重新计算属性();

            _日志器.LogInformation("玩家 {玩家名称} 脱下装备 {装备名称} 从 {槽位} 槽位",
                玩家.名称, 装备.名称, 槽位);

            // 发布装备脱下事件
            await _事件总线.发布事件(new 装备脱下事件
            {
                玩家 = 玩家,
                装备 = 装备,
                槽位 = 槽位
            });
        }
        else
        {
            _日志器.LogWarning("从玩家 {玩家名称} 装备列表移除装备失败", 玩家.名称);
        }

        return 移除成功;
    }

    /// <summary>
    /// 获取指定槽位的装备
    /// </summary>
    public 装备物品? 获取槽位装备(玩家 玩家, 装备槽位 槽位)
    {
        return 玩家.装备列表.FirstOrDefault(e => e is 装备物品 装备 && 装备.槽位 == 槽位) as 装备物品;
    }

    /// <summary>
    /// 获取玩家所有装备
    /// </summary>
    public Dictionary<装备槽位, 装备物品?> 获取玩家所有装备(玩家 玩家)
    {
        var 装备字典 = new Dictionary<装备槽位, 装备物品?>();
        foreach (装备槽位 槽位 in Enum.GetValues<装备槽位>())
        {
            装备字典[槽位] = 获取槽位装备(玩家, 槽位);
        }
        return 装备字典;
    }

    /// <summary>
    /// 修理装备
    /// </summary>
    public async Task<bool> 修理装备(玩家 玩家, 装备物品 装备)
    {
        if (装备.耐久度 >= 装备.最大耐久度)
        {
            _日志器.LogInformation("装备 {装备名称} 耐久度已满，无需修理", 装备.名称);
            return true;
        }

        装备.耐久度 = 装备.最大耐久度;

        _日志器.LogInformation("玩家 {玩家名称} 修理装备 {装备名称}", 玩家.名称, 装备.名称);

        // 发布装备修理事件
        await _事件总线.发布事件(new 装备修理事件
        {
            玩家 = 玩家,
            装备 = 装备
        });

        return true;
    }

    /// <summary>
    /// 装备耐久度消耗
    /// </summary>
    public async Task 消耗装备耐久(玩家 玩家, 装备物品 装备, int 消耗量 = 1)
    {
        装备.耐久度 = Math.Max(0, 装备.耐久度 - 消耗量);

        if (装备.耐久度 <= 0)
        {
            _日志器.LogWarning("装备 {装备名称} 耐久度耗尽", 装备.名称);

            // 自动脱下损坏的装备
            await 脱下装备(玩家, 装备.槽位);

            // 发布装备损坏事件
            await _事件总线.发布事件(new 装备损坏事件
            {
                玩家 = 玩家,
                装备 = 装备
            });
        }
    }

    /// <summary>
    /// 获取所有已注册装备
    /// </summary>
    public List<装备物品> 获取所有装备()
    {
        return _装备字典.Values.ToList();
    }

    /// <summary>
    /// 根据槽位获取装备列表
    /// </summary>
    public List<装备物品> 根据槽位获取装备(装备槽位 槽位)
    {
        return _装备字典.Values.Where(e => e.槽位 == 槽位).ToList();
    }

    /// <summary>
    /// 注册事件处理
    /// </summary>
    private void 注册事件处理()
    {
        // 处理战斗开始事件，检查装备耐久度
        _事件总线.订阅事件<战斗开始事件>(async 事件 =>
        {
            foreach (var 玩家 in 事件.战斗上下文.玩家队伍)
            {
                foreach (var 装备 in 玩家.装备列表.OfType<装备物品>())
                {
                    if (装备.耐久度 <= 0)
                    {
                        _日志器.LogWarning("玩家 {玩家名称} 的装备 {装备名称} 耐久度为零，自动脱下",
                            玩家.名称, 装备.名称);
                        await 脱下装备(玩家, 装备.槽位);
                    }
                }
            }
            await Task.CompletedTask;
        });

        // 处理技能使用事件，消耗武器耐久度
        _事件总线.订阅事件<技能使用事件>(async 事件 =>
        {
            if (事件.施法者 is 玩家 玩家)
            {
                var 武器 = 获取槽位装备(玩家, 装备槽位.武器);
                if (武器 != null)
                {
                    // 注意：这里需要修复事件类引用
                    // await 消耗装备耐久(玩家, 武器);
                }
            }
            await Task.CompletedTask;
        });
    }
}

